package com.wk.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {


    /**
     * 创建过滤器工厂
     *
     * 配置拦截规则
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
//        配置拦截规则  需要配置哪些页面拦截 哪些页面不拦截
        /**
         * 在map中配置拦截规则
         * 配置方法
         * map的 key 为要配置的路径 value对应要不要拦截
         * value有两种写法
         * anon  匿名可访问 不拦截 不强制登录
         * authc 认证可访问  需要登录之后才能访问的页面
         *
         * 支持统配符 *
         *
         * 不能写 /** 有bug
         */
        Map map = new HashMap();
        map.put("/login.jsp","anon");
        map.put("/login/*","anon");

        map.put("/main.jsp", "authc");
        map.put("/guru/*", "authc");
        map.put("/menu/*", "authc");
        map.put("/jsp/*", "authc");


        factoryBean.setFilterChainDefinitionMap(map);
//        设置安全管理器
        factoryBean.setSecurityManager(securityManager);

        return factoryBean;
    }

    /**
     * @Bean 注解所在的方法
     * 方法的形参 对应的类型 如果在Spring工厂中 存在一个对象
     * Spring 会自动的把对象装配到形参的位置
     */
    @Bean
    public DefaultWebSecurityManager securityManager(MyAuthorRealm myAuthorRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        需要设置一个自定义Realm

        securityManager.setRealm(myAuthorRealm);
        return securityManager;
    }

    /**
     * 创建自定义的Realm
     */
    @Bean
    public MyAuthorRealm myAuthorRealm(HashedCredentialsMatcher hashedCredentialsMatcher){

        MyAuthorRealm myAuthorRealm = new MyAuthorRealm();

        //声明使用加密
        myAuthorRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return myAuthorRealm;
    }

    /**
     * 密码校验规则HashedCredentialsMatcher
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //指定加密方式为MD5 SHA
        credentialsMatcher.setHashAlgorithmName("MD5");
        //加密次数 散列次数   必须和注册时候散列次数保持一致
        credentialsMatcher.setHashIterations(1024);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }

    /**
     *  开启shiro aop注解支持
     *  使用代理方式;所以需要开启代码支持;否则@RequiresRoles等注解无法生效
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
